package com.northpool.operator.analysis.grid;

import org.apache.commons.lang3.ArrayUtils;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.grid.GridElement;
import org.geotools.grid.GridFeatureBuilder;
import org.geotools.grid.Grids;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.geom.PrecisionModel;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.geometry.BoundingBox;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HexGrid {

    private static final GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel());

    /**
     * 生成蜂巢
     *
     * @param bounds  范围
     * @param sideLen 边长
     * @return List<Polygon>
     */
    public List<Polygon> createGrid(BoundingBox bounds, float sideLen) {
        try {
            ReferencedEnvelope gridBounds = new ReferencedEnvelope(bounds.getMinX(), bounds.getMaxX(), bounds.getMinY(), bounds.getMaxY(), DefaultGeographicCRS.WGS84);

            // 创建一个特征类型
            List<Polygon> polygons = new ArrayList<>();
            SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
            tb.setCRS(DefaultGeographicCRS.WGS84);

            tb.setName("grid");
            tb.add(
                    GridFeatureBuilder.DEFAULT_GEOMETRY_ATTRIBUTE_NAME,
                    Polygon.class,
                    gridBounds.getCoordinateReferenceSystem());
//            tb.add("id", Integer.class);
            SimpleFeatureType TYPE = tb.buildFeatureType();
            GridFeatureBuilder gridFeatureBuilder = new GridFeatureBuilder(TYPE) {
                @Override
                public void setAttributes(GridElement gridElement, Map<String, Object> map) {
                    Coordinate[] vertices = gridElement.getVertices();
                    Coordinate[] ring = ArrayUtils.insert(vertices.length, vertices, vertices[0]);
                    Polygon polygon = geometryFactory.createPolygon(ring);
                    polygons.add(polygon);
                }
            };
//            Grids.createOvalGrid(gridBounds, sideLen, gridFeatureBuilder);
//            Grids.createSquareGrid(gridBounds, sideLen,0 , gridFeatureBuilder);
            Grids.createHexagonalGrid(gridBounds, sideLen,0, gridFeatureBuilder);
//            Hexagons.createGrid(gridBounds, sideLen, HexagonOrientation.ANGLED, gridFeatureBuilder);

            return polygons;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        HexGrid hexGrid = new HexGrid();

        // 示例范围
        double minX = 116.25;
        double minY = 39.75;
        double maxX = 116.5;
        double maxY = 40.0;
        float sideLen = 0.005f; //边长度，单位度

        List<Polygon> polygons = hexGrid.createGrid(new ReferencedEnvelope(minX, maxX, minY, maxY, DefaultGeographicCRS.WGS84), sideLen);
        for (Polygon polygon : polygons) {
            System.out.println(polygon.toString());
        }
        if (polygons != null) {
            System.out.println("生成了 " + polygons.size() + " 个六边形");
        } else {
            System.out.println("生成六边形失败");
        }

        System.out.println("共耗时 " + (System.currentTimeMillis() - start) + " ms");
    }
}
